﻿using Furion.CMS.Core;
using Furion.CMS.Core.Handlers;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.TaskScheduler;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Domain
{
    public class CrontabInfoFormatHandler : AuditLogFormatHandler
    {
        public override string GetRowKey(DbContext context, object entityValues, params string[] formatArgs)
        {
            var instanceName = "未知";
            if (entityValues is PropertyValues values)
            {
                Scoped.Create((_, scope) =>
                {
                    var services = scope.ServiceProvider;
                    // 获取当前所有的工作任务集合
                    var jobs = services.GetServices<ICrontabDefinition>();
                    var instancePath = values.GetValue<string>(nameof(CrontabInfo.InstancePath));
                    var jobInstance = jobs.FirstOrDefault(t => t.GetType().FullName == instancePath);
                    instanceName = jobInstance?.DisplayName ?? instanceName;
                });
            }
            return instanceName;
        }
    }

    /// <summary>
    /// 后台任务信息
    /// </summary>
    [OperateRecord("定时任务配置")]
    public class CrontabInfo : PrivateEntity<Guid>, IEntityTypeBuilder<CrontabInfo>, IEntityChangedListener<CrontabInfo>
    {
        public CrontabInfo()
        {
            ExecuteRecords = new HashSet<CrontabExecuteRecord>();
            CreatedTime = DateTimeOffset.UtcNow;
        }

        /// <summary>
        /// 目标操作
        /// </summary>
        [Required]
        [OperateRecord("定时任务配置", true, typeof(CrontabInfoFormatHandler))]
        public string InstancePath { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// Cron 表达式
        /// </summary>
        [MaxLength(100), Required]
        [OperateRecord("Cron表达式")]
        public string CronExpression { get; set; }
        /// <summary>
        /// 是否启用
        /// </summary>
        [OperateRecord("是否启用")]
        public bool Enable { get; set; }
        /// <summary>
        /// 执行记录
        /// </summary>
        public virtual ICollection<CrontabExecuteRecord> ExecuteRecords { get; set; }

        public void Configure(EntityTypeBuilder<CrontabInfo> entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            entityBuilder.UseDefaultTableNameDefine();

            entityBuilder.HasMany(p => p.ExecuteRecords)
                .WithOne(p => p.Task)
                .HasForeignKey(p => p.TaskId);
        }

        public void OnChanged(CrontabInfo newEntity, CrontabInfo oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)
        {
            switch (state)
            {
                case EntityState.Modified:
                case EntityState.Unchanged:
                    // 当任务的启用状态与Cron表达式发生变化时会停止当前执行的任务
                    if ((oldEntity != null && oldEntity.Enable.Equals(newEntity.Enable))
                        || (oldEntity != null && oldEntity.CronExpression.Equals(newEntity.CronExpression)))
                    {
                        SpareTime.Cancel(newEntity.InstancePath);
                    }
                    break;
                case EntityState.Deleted:
                    // 删除时会尝试去停止任务
                    SpareTime.Cancel(newEntity.InstancePath);
                    break;
            }
        }
    }
}
